package test.sort.pyramidsort;

import com.alibaba.rocketmq.shade.com.alibaba.fastjson.JSON;
import com.alibaba.rocketmq.shade.com.alibaba.fastjson.JSONObject;
import test.sort.FileUtils;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SortAsc implements Runnable{

    boolean sortCompleted=false;

    SortAsc parent=null;

//    SortAsc[] childs;

    /**
     * childs的缓存，用语添加子级，添加完之后转为数组释放多与空间
     */
    List<SortAsc> childsTemp=null;


    //线程序号
    int xuhao;


    int[] arrs;


    int[] maxvalues;
    int[] minvalues;

    ExecutorService cachedThreadPool ;


    public SortAsc(int[] rawArr){
        this.arrs=rawArr;
    }

    public SortAsc(){
        init();
    }

    public void init(){
        cachedThreadPool= Executors.newCachedThreadPool();
    }



    @Override
    public void run() {
        sort();
    }

    public boolean hasSort(){

        return !sortCompleted;
    }

    public int getMinvalue(){
        if(childsTemp==null){
            return arrs[0];
        }
        return 0;
    }

    public int getMaxvalue(){
        if(childsTemp==null){
            return arrs[arrs.length-1];
        }
       return 0;
    }

    public  void sort(){
        if(childsTemp!=null){
//            System.out.println(Thread.currentThread()+"开始排序.childsTemp");
            for (SortAsc sortAsc:childsTemp) {
               cachedThreadPool.execute(sortAsc);
            }
            cachedThreadPool.shutdown();
            while (!cachedThreadPool.isShutdown()){
//                System.out.println("while");
            }

            try {
//                FileUtils fileUtils=new FileUtils("/tmp/win/sort.txt");
                while(exchangeSort()){
//                System.out.println("经过排序");
//                    out(fileUtils.getOut(),"\t");
//                    fileUtils.getOut().write("\n");
                }
//                fileUtils.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            ;

//            int count=minvalues.length;
//            for (int i = 0, j = i; i < count; j = ++i) {
//                int ai = minvalues[i + 1];
//                while (ai < minvalues[j]) {
//                    minvalues[j + 1] = minvalues[j];
//                    if (j-- == 0) {
//                        break;
//                    }
//                    minvalues[j + 1] = ai;
//                }
//
//            }


        }else{
//            System.out.println(Thread.currentThread()+"开始排序.Arrays.sort");
            Arrays.sort(arrs);

        }
//        System.out.println(Thread.currentThread()+"排序完成");
        sortCompleted=true;

    }

    /**
     * 插入并向右移动数据
     * @param index 插入位置
     * @param tmp   要插入的值
     */
    public void insertElementRight(int index,int tmp){
        int count=index==0?index:index-1;
        for (int i = arrs.length-1; i >count; i--) {
            arrs[i]=arrs[i-1];
        }
        arrs[index]=tmp;
    }

    /**
     * 插入并向右移动数据
     * @param index 插入位置
     * @param tmp   要插入的值
     */
    public void insertElementLeft(int index,int tmp){
        int count=index;
        for (int i = 0; i <index; i++) {
            arrs[i]=arrs[i+1];
        }
        arrs[index]=tmp;
    }

    /**
     * 交换该对象里面的最大值
     * @param tmp
     * @return
     */
    public int swapMaxValue(int tmp){
        int a=arrs[arrs.length-1];
        int low=0;
        int high=arrs.length-1;
        int middle=0;

        int maxindex=high;


        while(low <= high){
            middle = (low + high) / 2;
//            System.out.println("middle="+middle);
            if(arrs[middle] > tmp){
                if(middle>0){
                    if(arrs[middle-1]<tmp){
                        insertElementRight(middle,tmp);
                        return a;
                    }
                }else if(middle==0){
                    insertElementRight(middle,tmp);
                    return a;
                }
                high = middle - 1;
            }else if(arrs[middle] <= tmp){
                if(middle<maxindex){
                    if(arrs[middle+1]>=tmp){
                        insertElementRight(middle+1,tmp);
                        return a;
                    }
                }else if(middle==maxindex){
                    insertElementRight(middle,tmp);
                    return a;
                }
                low = middle + 1;
            }
        }

        System.out.println("交换出错");
        throw new NullPointerException("交换出错");
    }




   public void exchangeSort(SortAsc sortAsc){
//       System.out.println("exchangeSort");
        do {
//            println();
//            sortAsc.println();
            int tmp = arrs[0];
            tmp=sortAsc.swapMaxValue(tmp);
//            System.out.println("tmp="+tmp);
//            println();
//            sortAsc.println();

            int low=1;
            int high=arrs.length-1;
            int middle=0;

            int maxindex=high;


            while(low <= high){
                middle = (low + high) / 2;
//                System.out.println("min_middle="+middle);
                if(arrs[middle] > tmp){
                    if(middle>0){
                        if(arrs[middle-1]<tmp){
                            insertElementLeft(middle-1,tmp);
                            break;
                        }
                    }else if(middle==0){
                        insertElementLeft(middle,tmp);
                        break;
                    }
                    high = middle - 1;
                }else if(arrs[middle] <= tmp){
                    if(middle<maxindex){
                            if(arrs[middle+1]>=tmp){
//                                System.out.println("arrs[middle+1]>=tmp");
                                insertElementLeft(middle,tmp);
                                break;
                            }
                    }else if(middle==maxindex){
//                        System.out.println("middle=maxindex");
                        insertElementLeft(middle,tmp);
                        break;
                    }
                    low = middle + 1;
                }
            }

//            System.out.printf("end-------");
//            println();
//            sortAsc.println();


        }while(getMinvalue()<sortAsc.getMaxvalue());

   }



    public boolean exchangeSort(){
        cachedThreadPool = Executors.newCachedThreadPool();
        boolean sort=false;
        int count = childsTemp.size();
        List exchangeList=new ArrayList();
        for (int i=0,j=i;i<count-1;j=++i) {
            SortAsc sortAsc=childsTemp.get(i+1);
            SortAsc sortAsc2=null;
            int jTmp=0;
            while(sortAsc.getMinvalue()<childsTemp.get(j).getMaxvalue()){
                if(!exchangeList.contains(childsTemp.get(j))){
                    sortAsc2=childsTemp.get(j);
                    jTmp=j;
                }
                if (j-- == 0) {
                    break;
                }
            }
            if(sortAsc2!=null){
//                System.out.println("i="+i+",j="+jTmp);
                exchangeList.add(sortAsc);
                exchangeList.add(sortAsc2);
                sort=true;
                int finalJ = j;
                SortAsc finalSortAsc = sortAsc2;
//                cachedThreadPool.execute(()->{
                    sortAsc.exchangeSort(finalSortAsc);
//                });
            }

        }
        cachedThreadPool.shutdown();
        while(!cachedThreadPool.isShutdown()){
        }
        return sort;
    }


    public void childOver(){
        maxvalues=new int[childsTemp.size()];
        minvalues=new int[childsTemp.size()];

    }

    public void addChild(SortAsc sortAsc){
        if(childsTemp==null){
            childsTemp=new ArrayList<>();
        }
        childsTemp.add(sortAsc);
    }

    public void out(FileWriter out,String splitter) throws IOException {
        if(childsTemp==null){
            for (int i = 0; i < arrs.length; i++) {
                out.write(arrs[i]+splitter);
            }
            return;
        }
        for (SortAsc sortAsc:childsTemp ) {
            sortAsc.out(out,splitter);
        }
    }


    public void println() {
        System.out.println(JSON.toJSONString(arrs));
    }
}
